
importScripts("./libshared/earcut.js");
importScripts("./libshared/Point.js");
importScripts("./libshared/Pbf.js");
importScripts("./libshared/MVTData.js");
importScripts("./libshared/MVTFeature.js");
importScripts("./libshared/MVTLayer.js");

importScripts("./core/mathengine.js");
importScripts("./core/vector2.js");
importScripts("./core/vector3.js");
importScripts("./core/vector4.js");
importScripts("./core/matrix3f.js");
importScripts("./core/matrix4f.js");
importScripts("./core/matrix4d.js");
importScripts("./core/size.js");
importScripts("./core/bounds.js");
importScripts("./core/projection.js");
importScripts("./core/triangulator.js");
importScripts("./core/coordsys.js");
importScripts("./core/tilecoordsys.js");

onmessage = function(event) {
    let data = event.data;
    let coords = parseJson(data);
    let message = getLayoutsAndBuffers(coords)
    postMessage(message);
}
function getLayoutsAndBuffers(coords){
    let layouts = [];
    let buffers = [];
    let min=10;let max = 60;
    let center = projectToWorld([coords[0][0][0], coords[0][0][1], 0.1]);
    let positionArr = [],parcent_Arr = [], dstPosition = [];
    for(let x=0;x<coords.length;x++){
        let coordinates = coords[x];//[[],[]]
        let vecticesAndPercent = getVecticesAndPercentByCoordinates(coordinates,min,max);//[[],[],[],]
        let vectices = vecticesAndPercent.coords;
        let percent = vecticesAndPercent.percent;
        let points = [],points2=[];
        let parcentArr = [];
        for(let i=0;i<vectices.length;i++){
            let vector = vectices[i];
            vector[2] = vector[2]||0;
            let position = projectToWorld([vector[0], vector[1], 0.1]);
            if (i < vectices.length - 1) {
                points.push(position.x - center.x, position.y - center.y, position.z);
                parcentArr.push(percent);
            }
            if (i > 0){
                points2.push(position.x - center.x, position.y - center.y, position.z);
            }

        }
        positionArr = positionArr.concat(points);
        parcent_Arr = parcent_Arr.concat(parcentArr);
        dstPosition = dstPosition.concat(points2);
    }
    let layout = {
        attribs: [
            {name: 'position', itemSize: 3, normalized: 0, type: 0, index:0},
            {name: 'dsPosition', itemSize: 3, normalized: 0, type: 0, index:1},
            {name: 'percent', itemSize: 1, normalized: 0, type: 0, index:2},
        ],
        // index: {name: 'index', itemSize: 1, normalized: 0, type: 0, index: 7 * i + 6}
    };
    layouts.push(layout);
    buffers[0] = positionArr;
    buffers[1] = dstPosition;
    buffers[2] =parcent_Arr;
    return {
        layouts:layouts,
        buffers:buffers,
        origin:[coords[0][0][0], coords[0][0][1], 0.1]
    }

}
const WORLD_SIZE = 512;

function projectToWorld(coords){
    let coordSys = new TileCoordSys();
    var projected = [
        coordSys.mercatorXfromLng(coords[0]) * WORLD_SIZE,
        coordSys.mercatorYfromLat(coords[1]) * WORLD_SIZE
    ];

    var pixelsPerMeter = coordSys.projectedUnitsPerMeter(coords[1]);

    //z dimension
    var height = coords[2] || 0;
    projected.push( height * pixelsPerMeter );
    var result ={
        x:projected[0],
        y:projected[1],
        z: projected[2]
    }
    return result;
}

function parseJson(jsonData){
    let coords = [];

    if(jsonData.hasOwnProperty('features')){
        let features = jsonData.features;
        for(let i=0;i<features.length;i++){
            let feature = features[i];
            let geometry = feature['geometry'];
            let coordinates = geometry["coordinates"];
            coords.push(coordinates);
        }
    }else{
        coords = jsonData;
    }

    return coords;
}
/*
coordinates: [[],[]]
 */
function getVecticesAndPercentByCoordinates(coordinates,min,max){
    let sCoord = coordinates[0];
    let eCoord = coordinates[1];
    let lon1 = sCoord[0], lat1 = sCoord[1], lon2 = eCoord[0], lat2 = eCoord[1], count = Math.random()*(max-min)+min;//30-100
    count+=2;
    let coords = new parabola(lon1,lat1,0,lon2,lat2,0,count,0.0).get();
    let percent = (count-min)/(max-min);
    return {
        coords:coords,
        percent:percent
    };
}
function parabola(lon1,lat1,high1,lon2,lat2,high2,count,angle)
{

    this.lon1 = lon1;
    this.lat1 = lat1;
    //将高度转换为度 计算时单位统一
    this.high1 = high1 / 1000 / 111;
    this.lon2 = lon2;
    this.lat2 = lat2;
    this.high2 = high2 / 1000 / 111;
    this.count = count;
    if(angle && typeof angle == 'number'){
        this.angle = angle*Math.PI/180
    }else{
        this.angle = 0;
    }
    // if(parseInt(angle) === 0)
    // {
    //     this.count = 2;
    // }
    this.get = function(){
        var result = [];
        result = this.getAllPoint();
        return result;
    }
    this.getAllPoint = function(){
        var lon1 = this.lon1, lat1 = this.lat1, high1 = this.high1, lon2 = this.lon2, lat2 = this.lat2, high2 = this.high2, count = this.count;
        // 转换到坐标系中两点间距离
        var  lengthX = Math.sqrt(Math.pow((lon1 - lon2), 2) + Math.pow((lat1 - lat2),2));
        // 中点的高度，按照入射角45°计算
        var  centerHigh = lengthX / 2 * Math.tan(this.angle)+ (high1 > high2 ? high1 : high2);
        // sincos用于将坐标系中的点坐标，转换为经纬度
        var  sinIndex = (lat2 - lat1) / lengthX;
        var  cosIndex = (lon2 - lon1) / lengthX;
        // 带入三点坐标后等式参数
        var parameter = [[],[],[]];
        //带入第一个点后，等式y的另一侧a/b/c前的参数
        parameter[0][0] = 0;
        parameter[0][1] = 0;
        parameter[0][2] = 1;
        //带入中心点后，等式y的另一侧a/b/c前的参数
        parameter[1][0] = Math.pow((lon1 - lon2)/2, 2) + Math.pow((lat1 - lat2)/2,2);
        parameter[1][1] = Math.sqrt(Math.pow((lon1 - lon2)/2, 2) + Math.pow((lat1 - lat2)/2,2));
        parameter[1][2] = 1;
        //带入第二个点后，等式y的另一侧a/b/c前的参数
        parameter[2][0] = Math.pow(lengthX, 2);
        parameter[2][1] = lengthX;
        parameter[2][2] = 1;
        // 带入三点坐标后等式值
        var  parameterValue = [high1,centerHigh,high2];
        // 通过克拉默法则计算参数值
        var  parameterResult = CramerRule(parameter,parameterValue);
        // length为坐标系中相邻两点的距离
        var  length = lengthX / count;
        // 临时变量，抛物线中某点的坐标
        var high;
        var lon;
        var lat;
        var  result = [];
        for(var i = 0;i <= count;i++){
            high = getH(i * length,parameterResult,lengthX);
            lon = lon1 + length * cosIndex * i;
            lat = lat1 + length * sinIndex * i;
            var  temp = [];
            temp.push(lon);
            temp.push(lat);
            temp.push(high);
            result.push(temp);
        }
        return result;
    }
    function getH(x, parameterResult, lengthX)
    {
        var  result = parameterResult[0] * Math.pow(x, 2) + parameterResult[1] * x + parameterResult[2];
        //高度需要的是米，将度转换成米
        result = result * 1000 * 100;
        return result;
    }
    function CramerRule(parameter,parameterResult)
    {
        //构建行列式并计算克拉默参数
        var d = parameter[0][0] *  parameter[1][1] * parameter[2][2] + parameter[0][1] *  parameter[1][2] * parameter[2][0] + parameter[1][0] *  parameter[2][1] * parameter[0][2]
            - parameter[0][2] *  parameter[1][1] * parameter[2][0] - parameter[2][1] *  parameter[1][2] * parameter[0][0] - parameter[1][0] *  parameter[0][1] * parameter[2][2];
        var da = parameterResult[0] *  parameter[1][1] * parameter[2][2] + parameter[0][1] *  parameter[1][2] * parameterResult[2] + parameterResult[1] *  parameter[2][1] * parameter[0][2]
            - parameter[0][2] *  parameter[1][1] * parameterResult[2] - parameter[2][1] *  parameter[1][2] * parameterResult[0] - parameterResult[1] *  parameter[0][1] * parameter[2][2];
        var db = parameter[0][0] *  parameterResult[1] * parameter[2][2] + parameterResult[0] *  parameter[1][2] * parameter[2][0] + parameter[1][0] *  parameterResult[2] * parameter[0][2]
            - parameter[0][2] *  parameterResult[1] * parameter[2][0] - parameterResult[2] *  parameter[1][2] * parameter[0][0] - parameter[1][0] *  parameterResult[0] * parameter[2][2];
        var dc = parameter[0][0] *  parameter[1][1] * parameterResult[2] + parameter[0][1] *  parameterResult[1] * parameter[2][0] + parameter[1][0] *  parameter[2][1] * parameterResult[0]
            - parameterResult[0] *  parameter[1][1] * parameter[2][0] - parameter[2][1] *  parameterResult[1] * parameter[0][0] - parameter[1][0] *  parameter[0][1] * parameterResult[2];
        //计算出参数a、b、c的值
        var a = da/d;
        var b = db/d;
        var c = dc/d;
        var result = [a,b,c];
        return result;
    }
}